﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LexLib.LexemNameSpace;
using System.Reflection;


///Мы считаем, что expressionType является переменной, если имя - VarNameType, 
///в списке переменных тоько одно значение и список детей пуст
namespace TextEditor4.Parser
{
    /// <summary>
    /// Интерфейс для описания узла и листа дерева
    /// </summary>
    public interface IParseNodeType
    {
        /// <summary>
        /// хранит все, что наследуется от этого узла
        /// </summary>
        List<IParseNodeType> listOfChildren
        {
            get;
            set;
        }

        /// <summary>
        /// Имя узла. Имеет значение для переменных и функций
        /// </summary>
        string name
        { get; }

        /// <summary>
        /// Список переменных, обявленных(быть может, использованных) под этим узлом
        /// Играет значения для всех узлов
        /// </summary>
        List<string> usedVariables
        {
            get;
            set;
        }

        int begIndex
        {
            get;
            set;
        }

        int endIndex
        {
            get;
            set;
        }

    }

    /// <summary>
    /// Класс для описания узла последовательности действий
    /// </summary>
    public class SeqenseType : IParseNodeType
    {
        private List<IParseNodeType> _listOfChildren = new List<IParseNodeType>();
        private List<string> _usedVaribles = new List<string>();
        private int _begIndex;
        private int _endIndex;
        private string _name = null;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="bI">начало</param>
        public SeqenseType(int bI)
        {
            this._begIndex = bI;
        }

        public SeqenseType(int bI, string description)
        {
            this._begIndex = bI;
            this._name = description;
        }

        public void addChild(IParseNodeType node)
        {
            if (this._begIndex > node.begIndex)
            {
                this._begIndex = node.begIndex;
            }
            if (this._endIndex < node.endIndex)
            {
                this._endIndex = node.endIndex;
            }
            this._listOfChildren.Add(node);
            foreach (string str in node.usedVariables)
            {
                if (!this._usedVaribles.Contains(str))
                {
                    this._usedVaribles.Add(str);
                }
            }
        }
        #region IParseNodeType Memberse
        public List<IParseNodeType> listOfChildren
        {
            get { return _listOfChildren; }
            set
            {
                foreach (IParseNodeType tmp in value)
                {
                    _listOfChildren.Add(tmp);
                }
            }

        }

        public string name
        {
            get { return _name; }
        }

        public List<string> usedVariables
        {
            get { return _usedVaribles; }
            set
            {
                foreach (string tmp in value)
                {
                    _usedVaribles.Add(tmp);
                }
            }
        }
        public int begIndex
        {
            get { return _begIndex; }
            set { _begIndex = value; }
        }
        public int endIndex
        {
            get { return _endIndex; }
            set { _endIndex = value; }
        }
        #endregion
    }


    /// <summary>
    /// класс для описания элементарного действия.
    /// от него две ветки - перая на элемент слева от действия, вторая - на элемент справа
    /// пока используется для =(потом нужно включить булевские операции)
    /// </summary>
    public class ExpressionType : IParseNodeType
    {
        private List<IParseNodeType> _listOfChildren = new List<IParseNodeType>();
        private List<string> _usedVaribles = new List<string>();
        private int _begIndex;
        private int _endIndex;
        private string _name;

        /// <summary>
        /// конструктор от лексемы
        /// </summary>
        /// <param name="lexem"></param>
        public ExpressionType(Lexem lexem)
        {
            this._begIndex = lexem.beginIndex;
            this._endIndex = lexem.endIndex;
            this._name = lexem.TypeOfLexem.GetType().ToString();
            if (lexem.TypeOfLexem is VarNameType)
            {
                PropertyInfo myPI = lexem.TypeOfLexem.GetType().GetProperty("GetWord");
                this._usedVaribles.Add((string)myPI.GetValue(lexem.TypeOfLexem, null));
            }

        }
        /// <summary>
        /// констурктор от узла. Я его использую в парсере. 
        /// Интересно, зачем, если я могу оперировать с готовыми узлами? Хм...
        /// </summary>
        /// <param name="node"></param>
        public ExpressionType(IParseNodeType node)
        {
            this._begIndex = node.begIndex;
            this._endIndex = node.endIndex;
            this._name = node.name;
            foreach (IParseNodeType tmpNode in node.listOfChildren)
            {
                this._listOfChildren.Add(tmpNode);
            }
            foreach (string str in node.usedVariables)
            {
                if (!this._usedVaribles.Contains(str))
                {
                    this._usedVaribles.Add(str);
                }
            }
        }
        public void addChild(IParseNodeType node)
        {
            if (this._begIndex > node.begIndex)
            {
                this._begIndex = node.begIndex;
            }
            if (this._endIndex < node.endIndex)
            {
                this._endIndex = node.endIndex;
            }
            foreach (string str in node.usedVariables)
            {
                if (!this._usedVaribles.Contains(str))
                {
                    this._usedVaribles.Add(str);
                }
            }
            this._listOfChildren.Add(node);
        }

        #region IParseNodeType Members
        public List<IParseNodeType> listOfChildren
        {
            get { return _listOfChildren; }
            set
            {
                foreach (IParseNodeType tmp in value)
                {
                    _listOfChildren.Add(tmp);
                }
            }
        }

        public List<string> usedVariables
        {
            get { return _usedVaribles; }
            set
            {
                foreach (string tmp in value)
                {
                    _usedVaribles.Add(tmp);
                }
            }
        }
        public string name
        {
            get { return _name; }
            set
            {
                _name = value;
            }
        }
        public int begIndex
        {
            get { return _begIndex; }
            set { _begIndex = value; }
        }
        public int endIndex
        {
            get { return _endIndex; }
            set { _endIndex = value; }
        }
        #endregion
    }

}
